package org.codeblue.support.utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;

import com.alibaba.fastjson.JSON;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;

import com.fasterxml.jackson.core.JsonProcessingException;

/**
 * @ClassName: ReflectUtils
 * @Description: TODO(反射工具类)
 * @author mb.wang  
 * @date 2013-10-31 下午1:45:14
 * 
 */
public final class ReflectUtils {
	private static final Log log = LogFactory.getLog(ReflectUtils.class);
	
	/**
	 * @Title: executeMethod
	 * @Description: TODO(这里用一句话描述这个方法的作用)
	 * @author mb.wang  
	 * @date 2013-10-31 下午2:19:30
	 * @param newObj--对象
	 * @param method--方法
	 * @param params--参数
	 * @return Object  返回类型
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException 
	 * @throws JsonProcessingException 
	 */
	public static Object executeMethod(Object newObj,Method method,Object ...params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, JsonProcessingException{
		Object value = method.invoke(newObj, params);
		log.info(JSON.toJSONString(value));
		return value;
	}
	
	/**
	 * @Title: newInstance
	 * @Description: TODO(创建一个对象)
	 * @author mb.wang  
	 * @date 2013-10-31 下午1:54:05
	 * @param className
	 * @return  Object  返回类型
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws ClassNotFoundException
	 */
	public static Object newInstance(String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
		Class<?> cls=Class.forName(className); 
		return cls.newInstance();
	}

	/**
	 * @Title: parseReturnType
	 * @Description: TODO(方法的返回类型)
	 * @author mb.wang  
	 * @date 2013-10-31 下午2:07:37
	 * @param method
	 * @return Type  返回类型
	 */
	public static Type parseReturnType(Method method){
		Assert.notNull(method, "method must not be null");
		
		/*Type returnType = method.getGenericReturnType();// 返回类型
		
		 if (returnType instanceof ParameterizedType) 如果是泛型类型 {
	            Type[] types = ((ParameterizedType) returnType)
	                    .getActualTypeArguments();// 泛型类型列表
	            System.out.println("  TypeArgument: ");
	            for (Type type : types) {
	                System.out.println("   " + type);
	            }
	        }*/
		 return method.getGenericReturnType();
	}
	
	/**
	 * @Title: parseParamTypes
	 * @Description: TODO(获取方法的请求参数类型列表)
	 * @author mb.wang  
	 * @date 2013-10-31 下午2:22:54
	 * @param method
	 * @return Type[]  返回类型
	 */
	public static Type[] parseParamTypes(Method method){
		return  method!=null?method.getGenericParameterTypes():null;
	}
	
	/**
	 * @Title: parseParamTypes
	 * @Description: TODO(获取方法的请求参数类型列表)
	 * @author mb.wang  
	 * @date 2013-10-31 下午2:02:04
	 * @param clazz
	 * @param methodName
	 * @return Type[]  返回类型
	 */
	public static Type[] parseParamTypes(Class<?> clazz, String methodName){
        Assert.notNull(clazz, "Class must not be null");
        Assert.notNull(methodName, "Method name must not be null");
        
        Class<?>[] cls = null;
		Method method = findMethod(clazz, methodName, cls);
		
		/*Type[] paramTypeList = method.getGenericParameterTypes();// 方法的参数列表
       for (Type paramType : paramTypeList) {
        	log.info("  " + paramType);// 参数类型
            if (paramType instanceof ParameterizedType) 如果是泛型类型 {
                Type[] types = ((ParameterizedType) paramType)
                        .getActualTypeArguments();// 泛型类型列表
                log.info("  TypeArgument: ");
                for (Type type : types) {
                	log.info("   " + type);
                }
            }
        }*/
		return  method!=null?method.getGenericParameterTypes():null;
	}
	
	/**
	 * @Title: findMethod
	 * @Description: TODO(获取方法)
	 * @author mb.wang  
	 * @date 2013-10-31 下午1:48:45
	 * @param clazz
	 * @param methodName
	 * @param paramTypes
	 * @return Method 
	 */
	public static Method findMethod(Class<?> clazz, String methodName, Class<?>... paramTypes) {
        Assert.notNull(clazz, "Class must not be null");
        Assert.notNull(methodName, "Method name must not be null");
        
        Class<?> searchType = clazz;
        while (searchType != null) {
            //判断当前要反射的类是不是接口，如果是接口则取出接口的方法（包含父接口的方法），否则则取出类定义的方法(但排除继承的方法）
            Method[] methods = (searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods());
            for (Method method : methods) {
                //如果方法的名字等于name参数，并且方法的传参为空或与paramTypes相等
                if (methodName.equals(method.getName())
                        && (paramTypes == null || Arrays.equals(paramTypes, method.getParameterTypes())
                        ||Arrays.equals(paramTypes, atomTypeToReferenceTypes(method.getParameterTypes())))) {
                    return method;
                }
            }
            //如果没找到相应的方法，则对searchType的父类进行同样的查找
            searchType = searchType.getSuperclass();
        }
        return null;
    }

	/**
	 * @Title: atomTypeToReferenceTypes
	 * @Description: TODO(原子类型（也叫基本数据类型）转引用类型（也叫封装类型）)
	 * @author mb.wang  
	 * @date 2013-10-31 下午4:47:44
	 * @param clsTypes
	 * @return Class<?>[]  返回类型
	 */
	private static Class<?>[] atomTypeToReferenceTypes(Class<?>[] clsTypes){
		if(clsTypes==null)
			return null;
		
		int clsSize = clsTypes.length;
		Class<?>[] clsList = new Class<?>[clsSize];
		
		for(int i=0;i<clsSize;i++){
			Class<?> cls = clsTypes[i];
			
			if(cls.equals(int.class)){
				clsList[i] = Integer.class;
			}else if(cls.equals(long.class)){
				clsList[i] = Long.class;
			}else if(cls.equals(short.class)){
				clsList[i] = Short.class;
			}else if(cls.equals(double.class)){
				clsList[i] = Double.class;
			}else if(cls.equals(float.class)){
				clsList[i] = Float.class;
			}else if(cls.equals(boolean.class)){
				clsList[i] = Boolean.class;
			}else{
				clsList[i] = cls;
			}
		}
		
		return clsList;
	}
}
